using System;
using SimpleServiceBus.Utilities;

namespace SimpleServiceBus.Bus.Transport
{
    /// <summary>
    /// Defines the basic functionality of a transport to be used by SimpleServiceBus.
    /// </summary>
    public interface ITransport : IBackgroundService
    {
        /// <summary>
        /// Gets the number of worker threads currently running in the transport.
        /// </summary>
        int NumberOfWorkerThreads { get; set; }
        int MaxRetries { get; set; }

        void Send(MessageEnvelope m, params string[] destinations);

        /// <summary>
        /// Re-queues a message for processing at another time.
        /// </summary>
        /// <param name="m">The message to process later.</param>
        void ReceiveMessageLater(MessageEnvelope m);

        /// <summary>
        /// Access the underlying technology to get the number of unhandled messages.
        /// </summary>
        /// <returns>The number of pending messages.</returns>
        int GetNumberOfPendingMessages();

        ///// <summary>
        ///// Gets the address at which the transport receives messages.
        ///// </summary>
        string ReturnAddress { get; }
        
        event EventHandler<MessageReceivedEventArgs> MessageReceived;

        event EventHandler MessageProcessingStarted;
        event EventHandler MessageProcessingFinished;
        event EventHandler<MessageProcessingErrorEventArgs> MessageProcessingError;

        ///// <summary>
        ///// Causes the current message being handled to return to the queue.
        ///// </summary>
        //void AbortHandlingCurrentMessage();
    }

    /// <summary>
    /// Defines the arguments passed to the event handler of the
    /// <see cref="ITransport.MessageReceived"/> event.
    /// </summary>
    public class MessageReceivedEventArgs : EventArgs
    {
        /// <summary>
        /// Initializes a new MessageReceivedEventArgs.
        /// </summary>
        /// <param name="m">The messageEnvelope that was received.</param>
        public MessageReceivedEventArgs(MessageEnvelope m)
        {
            messageEnvelope = m;
        }

        private readonly MessageEnvelope messageEnvelope;

        /// <summary>
        /// Gets the messageEnvelope received.
        /// </summary>
        public MessageEnvelope MessageEnvelope
        {
            get { return messageEnvelope; }
        }
    }
}